package com.cartrentalsystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cartrentalsystem.domain.po.Car;
import com.cartrentalsystem.domain.po.Customers;
import com.cartrentalsystem.domain.po.Rental;
import com.cartrentalsystem.domain.vo.Result;
import com.cartrentalsystem.mapper.CarMapper;
import com.cartrentalsystem.mapper.RentalMapper;
import com.cartrentalsystem.service.ICarService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cartrentalsystem.service.ICustomersService;
import com.cartrentalsystem.service.IRentalService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.stream.Stream;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author LHD
 * @since 2025-06-15
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class CarServiceImpl extends ServiceImpl<CarMapper, Car> implements ICarService {

    private final RentalMapper rentalMapper;

    private final ICustomersService  customersService;

    @Override
    @Transactional
    public Result<Page<Car>> pageList(Integer page, Integer size,  Integer status, String brand){
        Page<Car> list = new Page<>(page, size);
        this.lambdaQuery()
                .eq(status != null, Car::getStatus, status)
                .like(brand != null, Car::getBrand, brand)
                .eq(Car::getDeleted, 0)
                .page(list);
        log.info("查询结果:{}", list);
        return Result.success(list);
    }

    @Override
    @Transactional
    public Result<String> add(Car car){
        log.info("添加车辆:{}", car);
        car.setDeleted(0);
        boolean save = this.save(car);
        log.info("车辆添加成功");
        return save ? Result.success("添加成功") : Result.fail("添加失败");
    }

    @Override
    @Transactional
    public Result<String> updateCar(Car car){
        log.info("修改车辆:{}", car);
        boolean update = this.updateById(car);
        log.info("车辆修改成功");
        return update ? Result.success("修改成功") : Result.fail("修改失败");
    }

    @Override
    @Transactional
    public boolean updateStatus(Integer id, Integer status, Double mileage, LocalDate returnTime){
        Car one = this.lambdaQuery()
                .eq(Car::getId, id)
                .eq(Car::getDeleted, 0)
                .one();
        log.info("更新车辆状态");
        if (status == 2 && returnTime !=null){
            // 说明是还车请求，要保持租赁表的一致性(租赁表中status为1表示进行中，2表示完成,还要加上租赁实际归还日期)
            Rental rental = rentalMapper.selectOne(new QueryWrapper<Rental>()
                    .eq("car_id", one.getId())
                    .eq("status", 1));
            if (rental == null) {
                throw new RuntimeException("当前车辆没有进行中的租赁记录");
            }
            rentalMapper.updateStatus(rental.getId(),one.getId(), 2, returnTime);
            one.setStatus(String.valueOf(1));
            mileage = one.getMileage() + mileage;
            one.setMileage(mileage);
            this.lambdaUpdate()
                    .eq(Car::getId, one.getId())
                    .update(one);

            customersService.lambdaUpdate()
                    .eq(Customers::getId, rental.getCustomerId())
                    .eq(Customers::getDeleted, 0)
                    .setSql("rental_times = rental_times + "+1)
                    .update();

            return true;
        }
        one.setStatus(String.valueOf(status));
        mileage = one.getMileage() + mileage;
        one.setMileage(mileage);
        return this.lambdaUpdate()
                .eq(Car::getId, id)
                .eq(Car::getDeleted, 0)
                .update(one);
    }


    @Override
    @Transactional
    public String[] getNames(){
        String[] names = this.list().stream()
                .filter(car -> car.getDeleted() != 1)
                .filter(car -> car.getStatus().equals("1"))
                .map(car -> car.getBrand() +" "+car.getModel()+" "+car.getPlateNumber())
                .toArray(String[]::new);
        return names;
    }

    @Override
    public Result<Page<Car>> getAvailable(Integer page, Integer size){
        Page<Car> list = new Page<>(page, size);
        this.lambdaQuery()
                .eq(Car::getStatus, 1)
                .eq(Car::getDeleted, 0)
                .page(list);
                return Result.success(list);
    }
}
